package com.cskt.petums.controller;

import com.cskt.common.constants.Constants;
import com.cskt.common.entity.vo.ResultVO;
import com.cskt.common.entity.vo.StatusEnum;
import com.cskt.common.utils.AliyunSmsUtil;
import com.cskt.common.utils.MathUtils;
import com.cskt.common.utils.RedisKeyUtils;
import com.cskt.petums.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

/**
 * 用户登录控制器
 *
 * @author admin
 * @date 2023/04/13 16:16
 **/
@RestController
@RequestMapping(value = "/sms")
public class SmsController {

    private static final Logger log = LoggerFactory.getLogger(SmsController.class);

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private UserService userService;

    @Value(value = "${sms.send.enable}")
    private boolean isSend;

    /**
     * 获取短信验证码
     *
     * @param phone    手机号
     * @param codeType 验证码类型
     * @return 响应结果
     */
    @PostMapping(value = "/sendSms")
    public ResultVO sendSms(String phone, Integer codeType) {

        //先验证手机号是否准确 
        if (!checkPhone(phone)) {
            log.info("手机号码不正确,phone：{}", phone);
            return ResultVO.error(StatusEnum.FAIL_UMS_PHONE_ERROR);
        }//判断短信类型是否正确
        if (!checkCodeType(codeType)) {
            log.info("短信类型不正确，codeType:{}", codeType);
            return ResultVO.error(StatusEnum.FAIL_UMS_SMS_CODE_TYPE_ERROR);
        }
        //判断短信发送频率
        if (!checkSmsCode(phone, codeType)) {
            log.info("短信验证码发送频率过高");
            return ResultVO.error(StatusEnum.FAIL_UMS_SMS_CODE_TOO_FAST);
        }
        try {
            //先生成短信验证码，存到redis中
            String code = MathUtils.random();
            log.debug("短信验证码,phone:{},code:{}",phone, code);
            //先发送，如果成功，再存入到redis
            if (isSend) {
                boolean result = AliyunSmsUtil.sendCaptcha(phone, code);
                if (result) {
                    //String key = PetUmsUtils.generateSmsRedisKey(codeType, phone);
                    String key = RedisKeyUtils.formatKeyWithPrefix(Constants.Redis.PREFIX_SMS,String.valueOf(codeType), phone);
                    stringRedisTemplate.opsForValue().set(key, code, Constants.Time.ALI_SMS_EFFECTIVE_TIME, TimeUnit.SECONDS);
                    return ResultVO.ok();
                }
                return ResultVO.error();
            } else {
                String key = RedisKeyUtils.formatKeyWithPrefix(Constants.Redis.PREFIX_SMS,String.valueOf(codeType), phone);
                stringRedisTemplate.opsForValue().set(key, code, Constants.Time.ALI_SMS_EFFECTIVE_TIME, TimeUnit.SECONDS);
                return ResultVO.ok();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private boolean checkSmsCode(String phone, Integer codeType) {
        String key = RedisKeyUtils.formatKeyWithPrefix(Constants.Redis.PREFIX_SMS,String.valueOf(codeType), phone);
        //取出当前key的过期时间
        Long expireTime = stringRedisTemplate.getExpire(key);
        // 短信验证码有效期为5分钟    如果过期时间大于4分钟，则不能重新发送
        return ObjectUtils.isEmpty(expireTime) || expireTime <= Constants.Time.ALI_SMS_CHECK_TIME;

    }
    
    private boolean checkPhone(String phone) {
        return phone.matches(Constants.Regular.PHONE_REGULAR_EXPRESSION);
    }
    
    private boolean checkCodeType(Integer codeType) {
        // 如果是不已定义的短信类型，不允许发送
        return codeType.equals(Constants.Sms.TYPE_REGISTER_OR_LOGIN);
    }

}
